#import "NSData+YLImageContentType.h"
#import <MobileCoreServices/MobileCoreServices.h>

// Currently Image/IO does not support WebP
#define kYLUTTypeWebP ((__bridge CFStringRef)@"public.webp")
// AVFileTypeHEIC is defined in AVFoundation via iOS 11, we use this without import AVFoundation
#define kYLUTTypeHEIC ((__bridge CFStringRef)@"public.heic")

@implementation NSData (YLImageContentType)

+ (YLImageFormat)yl_imageFormatForImageData:(nullable NSData *)data {
    if (!data) {
        return YLImageFormatUndefined;
    }
    uint8_t c;
    [data getBytes:&c length:1];
    switch (c) {
        case 0xFF:
            return YLImageFormatJPEG;
        case 0x89:
            return YLImageFormatPNG;
        case 0x47:
            return YLImageFormatGIF;
        case 0x49:
        case 0x4D:
            return YLImageFormatTIFF;
        case 0x52: {
            if (data.length >= 12) {
                //RIFF....WEBP
                NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
                if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) {
                    return YLImageFormatWebP;
                }
            }
            break;
        }
        case 0x00: {
            if (data.length >= 12) {
                //....ftypheic ....ftypheix ....ftyphevc ....ftyphevx
                NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(4, 8)] encoding:NSASCIIStringEncoding];
                if ([testString isEqualToString:@"ftypheic"]
                    || [testString isEqualToString:@"ftypheix"]
                    || [testString isEqualToString:@"ftyphevc"]
                    || [testString isEqualToString:@"ftyphevx"]) {
                    return YLImageFormatHEIC;
                }
            }
            break;
        }
    }
    return YLImageFormatUndefined;
}

+ (nonnull CFStringRef)yl_UTTypeFromYLImageFormat:(YLImageFormat)format {
    CFStringRef UTType;
    switch (format) {
        case YLImageFormatJPEG:
            UTType = kUTTypeJPEG;
            break;
        case YLImageFormatPNG:
            UTType = kUTTypePNG;
            break;
        case YLImageFormatGIF:
            UTType = kUTTypeGIF;
            break;
        case YLImageFormatTIFF:
            UTType = kUTTypeTIFF;
            break;
        case YLImageFormatWebP:
            UTType = kYLUTTypeWebP;
            break;
        case YLImageFormatHEIC:
            UTType = kYLUTTypeHEIC;
            break;
        default:
            // default is kUTTypePNG
            UTType = kUTTypePNG;
            break;
    }
    return UTType;
}

+ (YLImageFormat)yl_imageFormatFromUTType:(CFStringRef)uttype {
    if (!uttype) {
        return YLImageFormatUndefined;
    }
    YLImageFormat imageFormat;
    if (CFStringCompare(uttype, kUTTypeJPEG, 0) == kCFCompareEqualTo) {
        imageFormat = YLImageFormatJPEG;
    } else if (CFStringCompare(uttype, kUTTypePNG, 0) == kCFCompareEqualTo) {
        imageFormat = YLImageFormatPNG;
    } else if (CFStringCompare(uttype, kUTTypeGIF, 0) == kCFCompareEqualTo) {
        imageFormat = YLImageFormatGIF;
    } else if (CFStringCompare(uttype, kUTTypeTIFF, 0) == kCFCompareEqualTo) {
        imageFormat = YLImageFormatTIFF;
    } else if (CFStringCompare(uttype, kYLUTTypeWebP, 0) == kCFCompareEqualTo) {
        imageFormat = YLImageFormatWebP;
    } else if (CFStringCompare(uttype, kYLUTTypeHEIC, 0) == kCFCompareEqualTo) {
        imageFormat = YLImageFormatHEIC;
    } else {
        imageFormat = YLImageFormatUndefined;
    }
    return imageFormat;
}

@end
